----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    10:11:49 09/27/2013 
-- Design Name: 
-- Module Name:    mult_div - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity mult_div is
	port(	signControl, divControl, clock : in STD_LOGIC;
			a, b : in STD_LOGIC_VECTOR(31 downto 0);
			result : out STD_LOGIC_VECTOR(63 downto 0));
end mult_div;

architecture Behavioral of mult_div is
	component twos_complement_32 is
		port ( 	dataIn : in STD_LOGIC_VECTOR(31 downto 0);
					dataOut : out STD_LOGIC_VECTOR(31 downto 0));
	end component;
	
	component twos_complement_64 is
		port ( 	dataIn : in STD_LOGIC_VECTOR(63 downto 0);
					control : in STD_LOGIC_VECTOR(1 downto 0);
					dataOut : out STD_LOGIC_VECTOR(63 downto 0));
	end component;
	
	component mult is 
		port(	clock, load : in STD_LOGIC;
				m, r : in STD_LOGIC_VECTOR(31 downto 0);
				product : out STD_LOGIC_VECTOR(63 downto 0));
	end component;
	
	component div is
		port(	clock, load : in STD_LOGIC;
				n, d : in STD_LOGIC_VECTOR(31 downto 0);
				quotient : out STD_LOGIC_VECTOR(31 downto 0);
				remainder : out STD_LOGIC_VECTOR(31 downto 0));
	end component;
	
	signal load, signInitial : STD_LOGIC := '0';
	signal complementControl : STD_LOGIC_VECTOR(1 downto 0) := "00";
	signal aInitial, bInitial, aLoad, bLoad : STD_LOGIC_VECTOR(31 downto 0) := X"00000000";
	signal aNegative, bNegative : STD_LOGIC_VECTOR(31 downto 0) := X"00000000";
	signal multResult : STD_LOGIC_VECTOR(63 downto 0) := X"0000000000000000";
	signal resultIntermediate : STD_LOGIC_VECTOR(63 downto 0) := X"0000000000000000";
	signal quotient, remainder : STD_LOGIC_VECTOR(31 downto 0) := X"00000000";
begin
	mult1 : mult port map (clock, load, aLoad, bLoad, multResult);
	div1 : div port map(clock, load, aLoad, bLoad, quotient, remainder);
	twos1 : twos_complement_32 port map(a, aNegative);
	twos2 : twos_complement_32 port map(b, bNegative);
	twos3 : twos_complement_64 port map(resultIntermediate, complementControl, result);
process(clock)
begin
	if clock'event and clock = '1' then
		if aInitial /= a or bInitial /= b or signInitial /= signControl then
			aInitial <= a;
			bInitial <= b;
			signInitial <= signControl;
			load <= '1';
			
			if signControl = '0' then
				aLoad <= a;
				bLoad <= b;
			else
				if a(31) = '0' then
					aLoad <= a;
				else
					aLoad <= aNegative;
				end if;
				
				if b(31) = '0' then
					bLoad <= b;
				else
					bLoad <= bNegative;
				end if;
			end if;
		else
			load <= '0';
		end if;
		
		if signControl = '1' and 
			((a(31) = '1' and b(31) = '0') or (a(31) = '0' and b(31) = '1')) then
			if divControl = '0' then
				resultIntermediate <= multResult;
				complementControl <= "10";
			else
				resultIntermediate <= quotient & remainder;
				complementControl <= "01";
			end if;
		else
			if divControl = '0' then
				resultIntermediate <= multResult;
				complementControl <= "00";
			else
				resultIntermediate <= quotient & remainder;
				complementControl <= "00";
			end if;
		end if;
	end if;
end process;
end Behavioral;

